using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using OracleInternal.Common;

namespace OracleInternal.Network
{
	internal class EZConnect : INamingAdapter
	{
		internal class HostPort
		{
			internal string host;

			internal int port;

			internal HostPort()
			{
			}

			internal HostPort(string theHost, int thePort)
			{
				host = theHost;
				port = thePort;
			}
		}

		private static List<HostPort> HostPortPairs;

		private static char[] ampersand;

		private static char[] equalSign;

		private static char[] colonORslash;

		private static char[] commaORcolon;

		private static char[] slashORqmark;

		private static char[] commaColonORslash;

		private static char[] colonSlashORqmark;

		private static string BEGIN_DBL_SLASH;

		private const int DEFAULT_DATABASE_PORT = 1521;

		internal SqlNetOraConfig SNOConfig;

		public string ID => "EZConnect";

		public Hashtable Map => null;

		static EZConnect()
		{
			HostPortPairs = new List<HostPort>(10);
			ampersand = new char[1]
			{
				'&'
			};
			equalSign = new char[1]
			{
				'='
			};
			colonORslash = new char[2]
			{
				'/',
				':'
			};
			commaORcolon = new char[2]
			{
				',',
				':'
			};
			slashORqmark = new char[2]
			{
				'/',
				'?'
			};
			commaColonORslash = new char[3]
			{
				',',
				':',
				'/'
			};
			colonSlashORqmark = new char[3]
			{
				'/',
				':',
				'?'
			};
			BEGIN_DBL_SLASH = "//";
		}

		internal EZConnect()
		{
			SNOConfig = new SqlNetOraConfig(ConfigBaseClass.m_configParameters);
		}

		public string Resolve(string TNSAlias, out ConnectionOption CO, string InstanceName = null, string ServerIs = null)
		{
			if (TNSAlias == null)
			{
				CO = null;
				return null;
			}
			try
			{
				CO = ResolveSimple(TNSAlias, InstanceName, ServerIs);
			}
			catch (Exception inner)
			{
				throw new NetworkException(12550, inner);
			}
			try
			{
				if (CO.HostPortPairs.Count == 1 && (BadIPCache.BadHost(CO.Host).Value || Dns.GetHostAddresses(CO.Host) == null))
				{
					CO = null;
				}
			}
			catch (Exception)
			{
				CO = null;
			}
			if (CO == null)
			{
				return null;
			}
			return CO.ConnectData;
		}

		private static string GetValue(string TNSdesc, ref int POS, char[] EndChars = null)
		{
			EndChars = EndChars ?? colonORslash;
			POS++;
			int num = TNSdesc.IndexOfAny(EndChars, POS);
			if (num == -1)
			{
				num = TNSdesc.Length;
			}
			string result = TNSdesc.Substring(POS, num - POS);
			POS = num;
			return result;
		}

		private void BadIPandDNSExpansion(HostPort temp, List<HostPort> list)
		{
			IPAddress[] array = null;
			string host;
			if (temp == null || string.IsNullOrEmpty(host = temp.host))
			{
				return;
			}
			if (BadIPCache.BadHost(host).Value)
			{
				list.Insert(0, temp);
				return;
			}
			try
			{
				array = Dns.GetHostAddresses(host);
			}
			catch (Exception)
			{
			}
			if (array == null || array.Length == 0)
			{
				BadIPCache.Insert(host, host: true);
				list.Insert(0, temp);
				return;
			}
			int port = temp.port;
			for (int num = array.Length - 1; num >= 0; num--)
			{
				string text = array[num].ToString();
				temp = new HostPort(text, port);
				if (BadIPCache.Bad(text).Value)
				{
					list.Insert(0, temp);
				}
				else
				{
					list.Add(temp);
				}
			}
		}

		private ConnectionOption ResolveSimple(string TNSdesc, string InstanceName, string ServerIs)
		{
			ConnectionOption connectionOption = new ConnectionOption();
			string text = "";
			string text2 = "";
			int num = 0;
			int num2 = 0;
			TNSdesc = TNSdesc.Trim();
			if (ProviderConfig.m_bTraceLevelNetwork)
			{
				Trace.Write(OracleTraceLevel.Network, OracleTraceTag.Entry, OracleTraceClassName.EZConnect, OracleTraceFuncName.ResolveSimple);
				Trace.Write(OracleTraceLevel.Network, OracleTraceTag.None, OracleTraceClassName.EZConnect, OracleTraceFuncName.ResolveSimple, "Resolving EZConnect+ string: " + TNSdesc);
			}
			string text3 = ConfigBaseClass.m_configParameters["ssl_server_dn_match"] as string;
			connectionOption.SSLServerDNMatching = ((string.IsNullOrEmpty(text3) || SqlNetOraConfig.ParamValueIsTrue(text3)) ? true : false);
			try
			{
				connectionOption.Protocol = AddressResolution.DEFAULT_CONNECT_PROTOCOL;
				connectionOption.Server = ServerIs;
				connectionOption.TransportConnectTO = 60000;
				if ((num = TNSdesc.IndexOf("://")) != -1)
				{
					string text4 = TNSdesc.Substring(0, num);
					if (!string.IsNullOrEmpty(text4))
					{
						connectionOption.Protocol = text4;
					}
					num2 = num + 3;
				}
				else if (TNSdesc.StartsWith(BEGIN_DBL_SLASH))
				{
					num2 = 2;
				}
				if (!AddressResolution.All_PROTOCOLS.Contains<string>(connectionOption.Protocol, StringComparer.InvariantCultureIgnoreCase))
				{
					throw new NetworkException(12550);
				}
				int num3 = TNSdesc.IndexOf(',', num2);
				int num4 = TNSdesc.IndexOfAny(slashORqmark, num2);
				int num5 = num4;
				int num6 = 1521;
				if (num4 == -1)
				{
					num4 = (num5 = TNSdesc.Length);
				}
				connectionOption.HostPortPairs = new List<HostPort>(10);
				while (num5 > num2)
				{
					HostPort hostPort = new HostPort();
					num3 = (((num3 = TNSdesc.LastIndexOf(',', num5 - 1)) != -1) ? (num3 + 1) : num2);
					string text5 = TNSdesc.Substring(num3, num5 - num3).Trim();
					if (string.IsNullOrEmpty(text5))
					{
						throw new NetworkException(12550);
					}
					int num8;
					if (text5[0] == '[')
					{
						int num7 = text5.IndexOf(']', 1);
						if (num7 == -1)
						{
							throw new NetworkException(12550);
						}
						hostPort.host = text5.Substring(1, num7 - 1);
						num7++;
						hostPort.port = (((num8 = text5.IndexOf(':', num7)) != -1) ? int.Parse(text5.Substring(num8 + 1, text5.Length - (num8 + 1))) : num6);
					}
					else if ((num8 = text5.IndexOf(':')) != -1)
					{
						hostPort.port = int.Parse(text5.Substring(num8 + 1, text5.Length - (num8 + 1)));
						hostPort.host = text5.Substring(0, num8);
					}
					else
					{
						hostPort.port = num6;
						hostPort.host = text5;
					}
					num6 = hostPort.port;
					hostPort.host = hostPort.host.Trim('[', ']');
					BadIPandDNSExpansion(hostPort, connectionOption.HostPortPairs);
					num5 = num3 - 1;
					connectionOption.Host = hostPort.host;
					connectionOption.Port = hostPort.port;
				}
				num2 = num4;
				if (num2 < TNSdesc.Length)
				{
					if (TNSdesc[num2] == ':')
					{
						string value = GetValue(TNSdesc, ref num2);
						if (!string.IsNullOrEmpty(value) && !int.TryParse(value, out connectionOption.m_portNumber))
						{
							throw new NetworkException(12545);
						}
					}
					if (num2 < TNSdesc.Length && TNSdesc[num2] == '/')
					{
						connectionOption.ServiceName = GetValue(TNSdesc, ref num2, colonSlashORqmark);
						if (num2 < TNSdesc.Length)
						{
							if (TNSdesc[num2] == ':')
							{
								string value2 = GetValue(TNSdesc, ref num2, slashORqmark);
								if (string.IsNullOrEmpty(ServerIs))
								{
									connectionOption.Server = value2;
								}
							}
							if (num2 < TNSdesc.Length && TNSdesc[num2] == '/')
							{
								connectionOption.InstanceName = GetValue(TNSdesc, ref num2, colonSlashORqmark);
							}
						}
					}
				}
				if ((num2 = TNSdesc.IndexOf('?', num2)) != -1)
				{
					while (num2 < TNSdesc.Length)
					{
						string value3 = GetValue(TNSdesc, ref num2, equalSign);
						string value4 = GetValue(TNSdesc, ref num2, ampersand);
						value3 = value3.ToUpperInvariant().Trim();
						switch (value3)
						{
						case "WALLET_LOCATION":
							connectionOption.SSL_WALLET_DIRECTORY = value4;
							continue;
						case "SSL_SERVER_DN_MATCH":
							connectionOption.SSLServerDNMatching = SqlNetOraConfig.ParamValueIsTrue(value4);
							continue;
						case "SSL_SERVER_CERT_DN":
							connectionOption.SSLServerDN = value4;
							continue;
						case "HTTPS_PROXY":
							connectionOption.HTTPS_PROXY = value4;
							continue;
						case "HTTPS_PROXY_PORT":
							connectionOption.HTTPS_PROXY_PORT = int.Parse(value4);
							continue;
						case "RECV_BUF_SIZE":
							connectionOption.RBS = int.Parse(value4);
							continue;
						case "SEND_BUF_SIZE":
							connectionOption.SBS = int.Parse(value4);
							continue;
						case "SDU":
							connectionOption.SessionDataUnitSize = int.Parse(value4);
							continue;
						case "RETRY_COUNT":
							connectionOption.Retries = int.Parse(value4);
							continue;
						case "RETRY_DELAY":
							connectionOption.RetryDelay = int.Parse(value4);
							continue;
						case "TRANSPORT_CONNECT_TIMEOUT":
							connectionOption.TransportConnectTO = AddressResolution.TOConvert2Milli(Regex.Replace(value4, "\\s+", ""));
							continue;
						case "POOL_CONNECTION_CLASS":
							text2 = text2 + AddressResolution.BEG_CCLS + value4 + AddressResolution.END_ONE_BRACE;
							continue;
						case "POOL_PURITY":
							text2 = text2 + AddressResolution.BEG_PURE + value4 + AddressResolution.END_ONE_BRACE;
							continue;
						case "SERVICE_TAG":
							text2 = text2 + AddressResolution.BEG_STAG + value4 + AddressResolution.END_ONE_BRACE;
							continue;
						case "ENCRYPTION_CLIENT":
							connectionOption.Encryption = value4;
							continue;
						case "ENCRYPTION_TYPES_CLIENT":
							connectionOption.EncryptionTypes = value4;
							continue;
						case "CRYPTO_CHECKSUM_CLIENT":
							connectionOption.CryptoChecksum = value4;
							continue;
						case "CRYPTO_CHECKSUM_TYPES_CLIENT":
							connectionOption.CryptoChecksumTypes = value4;
							continue;
						}
						if (ProviderConfig.m_bTraceLevelNetwork)
						{
							Trace.Write(OracleTraceLevel.Network, OracleTraceTag.None, OracleTraceClassName.EZConnect, OracleTraceFuncName.ResolveSimple, "Got unknown EZConnect+ name/value : " + value3 + "/" + value4);
						}
						text = text + "(" + value3 + "=" + value4 + AddressResolution.END_ONE_BRACE;
					}
				}
				if (connectionOption.Port == -1)
				{
					connectionOption.Port = 1521;
				}
				if (connectionOption.ServiceName == null && SNOConfig.HostnameDefaultServiceIsHost)
				{
					connectionOption.ServiceName = connectionOption.Host;
				}
				connectionOption.Address = new StringBuilder().Append(AddressResolution.BEG_ADDR).Append(connectionOption.Protocol).Append(AddressResolution.BEG_HOST)
					.Append(connectionOption.Host)
					.Append(AddressResolution.BEG_PORT)
					.Append(connectionOption.Port)
					.Append(AddressResolution.END_TWO_BRACES)
					.ToString();
				StringBuilder stringBuilder = ((connectionOption.ServiceName == null) ? new StringBuilder().Append(AddressResolution.BEG_CONDATA) : new StringBuilder().Append(AddressResolution.BEG_CONDATA_SVC).Append(connectionOption.ServiceName).Append(AddressResolution.END_ONE_BRACE));
				stringBuilder = stringBuilder.Append(text2);
				if (connectionOption.Server != null)
				{
					stringBuilder = stringBuilder.Append(AddressResolution.BEG_SRVR).Append(connectionOption.Server).Append(AddressResolution.END_ONE_BRACE);
				}
				if (InstanceName != null)
				{
					stringBuilder = stringBuilder.Append(AddressResolution.BEG_INST).Append(InstanceName).Append(AddressResolution.END_ONE_BRACE);
				}
				else if (connectionOption.InstanceName != null)
				{
					stringBuilder = stringBuilder.Append(AddressResolution.BEG_INST).Append(connectionOption.InstanceName).Append(AddressResolution.END_ONE_BRACE);
				}
				if (AddressResolution.ful_CID != null)
				{
					stringBuilder = stringBuilder.Append(AddressResolution.ful_CID);
				}
				connectionOption.ConnectData = new StringBuilder().Append(AddressResolution.BEG_DESC).Append(text).Append(connectionOption.Address)
					.Append(stringBuilder)
					.Append(AddressResolution.END_TWO_BRACES)
					.ToString();
				return connectionOption;
			}
			catch (Exception)
			{
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelNetwork)
				{
					Trace.Write(OracleTraceLevel.Network, OracleTraceTag.Exit, OracleTraceClassName.EZConnect, OracleTraceFuncName.ResolveSimple);
				}
			}
		}

		public void Refresh()
		{
		}
	}
}
